/**
 *  Copyright (C) 2008-2013  Telosys project org. ( http://www.telosys.org/ )
 *
 *  Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *          http://www.gnu.org/licenses/lgpl.html
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.telosys.persistence.dbfeatures;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.telosys.common.logger.TelosysClassLogger;
import org.telosys.persistence.TelosysPersistenceException;
import org.telosys.persistence.sql.SqlTool;

public class SpecificSqlOperations {
	
    //-----------------------------------------------------------------------------
    private static final TelosysClassLogger logger = new TelosysClassLogger(SpecificSqlOperations.class);
    
    private void trace(String msg) {
    	logger.trace(msg);
    }
    
    //-----------------------------------------------------------------------------

	private final DbFeatures dbFeatures ;
	
    /**
     * Constructor
     * @param dbFeatures
     */
    public SpecificSqlOperations(DbFeatures dbFeatures) {
		super();
		this.dbFeatures = dbFeatures;
		trace("SpecificSqlOperations created with features " + dbFeatures);	
	}

    /**
     * Returns the Database Features used to perform the specific SQL operations
     * @return
     */
    public DbFeatures getDbFeatures() {
    	return dbFeatures ;
    }
    
    /**
     * Returns the 'for update' string if supported <br>
     * else throws an exception
     * @return
     */
    public String getForUpdateString() {
		trace("getForUpdateString()");
		String forUpdateString = dbFeatures.getForUpdateString();
    	if ( forUpdateString != null ) {
    		return forUpdateString ;
    	}
    	else {
    		throw new TelosysPersistenceException( AbstractDbFeatures.FOR_UPDATE_NOT_SUPPORTED + dbFeatures );
    	}
    }
    
	/**
	 * Executes the SQL request to retreive next value of the given sequence name
	 * @param connection
	 * @param sequenceName
	 * @return
	 */
	public long sequenceNextVal( Connection connection, String sequenceName ) {
		trace("sequenceNextVal( '" + sequenceName + "' )");	
    	long value = 0L ;
    	if ( dbFeatures.supportsSequences() ) {
    		String sql = dbFeatures.getSqlForSequenceNextVal(sequenceName);
    		value = execSql(connection, sql, "sequenceNextVal") ;
    	}
    	else {
    		throw new TelosysPersistenceException( AbstractDbFeatures.SEQUENCES_NOT_SUPPORTED + dbFeatures );
    	}
		trace("sequenceNextVal( '" + sequenceName + "' ) : return " + value );	
		return value ;
    }
    
    //---------------------------------------------------------------------------
    /**
     * Executes the given SQL request to get 'nextval' from the sequence
     * @param connection
     * @param sSqlRequest
     * @param sOperation
     * @return
     * @throws TelosysPersistenceException
     */
    private long execSql(Connection connection, String sSqlRequest, String sOperation) 
    {
		trace("execSql( '" + sSqlRequest + "' )");	
		
        String exceptionMsg = sOperation + "(SQL : " + sSqlRequest + ")";
        
        long value = 0L;
        //BigDecimal value = null ;
        
        Statement stmt = null;
        ResultSet rs = null;

        if (connection == null)
        {
            throw new TelosysPersistenceException(exceptionMsg + " : Connection is null");
        }
        try
        {
            stmt = connection.createStatement();
            rs = stmt.executeQuery(sSqlRequest);
            rs.next();
//    		trace("execSql( '" + sSqlRequest + "' ) : rs.getObject(1) : " + rs.getObject(1) );	
//    		trace("execSql( '" + sSqlRequest + "' ) : rs.getBigDecimal(1) : " + rs.getBigDecimal(1) );	
//    		trace("execSql( '" + sSqlRequest + "' ) : rs.getLong(1) : " + rs.getLong(1) );	
           
            value = rs.getLong(1);
            //value = rs.getBigDecimal(1);
            
        } catch (SQLException ex)
        {
            throw new TelosysPersistenceException(exceptionMsg, ex);
        } catch (Exception ex)
        {
            throw new TelosysPersistenceException(exceptionMsg, ex);
        } finally
        {
        	//--- Close the ResultSet and Statement, not the connection
            SqlTool.close(rs);
        }

        trace("execSql( '" + sSqlRequest + "' ) : return : " + value + " longValue : " + value );	
        
        return value;
        //return value.longValue();
    }    

}
